package common

import (
	"fmt"
	"log"
	"os"
	"runtime"
	"runtime/debug"
	"time"
)

func Stack(err any, es ...*error) {
	if err != nil {
		if len(es) > 0 {
			*(es[0]) = ErrPanic
		}
		f, e := os.OpenFile(time.Now().Format("stack20060102150405.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
		if e != nil {
			log.Println("OpenFile", e)
			log.Println("err:", err)
			log.Println(string(debug.Stack()))
			return
		}
		fmt.Fprintln(f, "err:", err)
		f.Write(debug.Stack())
		f.Close()
	}
}
func CheckFileIsExist(filename string) bool {
	var exist = true
	if _, err := os.Stat(filename); os.IsNotExist(err) {
		exist = false
	}

	return exist
}

func SafeCall(callback func(args ...interface{}) error, iargs ...interface{}) error {
	defer func() {
		if err := recover(); err != nil {
			log.Println(err)

			buf := make([]byte, 2048)
			n := runtime.Stack(buf, false)
			fmt.Println(string(buf[:n]))

			now := time.Now()
			filename := fmt.Sprintf("core_%d-%02d-%02d_%02d-%02d-%02d.dump", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(),
				now.Second())

			f, _err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_SYNC|os.O_RDWR, 0666)
			if _err != nil {
				log.Println(_err)
				return
			}
			defer f.Close()

			f.WriteString(fmt.Sprintln(err))
			f.Write([]byte{'\n'})
			f.WriteString(string(buf[:n]))
		}
	}()
	return callback(iargs...)
}

func SafeGo(f func(args ...interface{}) error, iargs ...interface{}) {
	go func() {
		defer func() {
			if err := recover(); err != nil {
				log.Println(err)

				buf := make([]byte, 2048)
				n := runtime.Stack(buf, false)
				fmt.Println(string(buf[:n]))

				now := time.Now()
				filename := fmt.Sprintf("core_%d-%02d-%02d_%02d-%02d-%02d.dump", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(),
					now.Second())

				f, _err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_SYNC|os.O_RDWR, 0666)
				if _err != nil {
					log.Println(_err)
					return
				}
				defer f.Close()

				f.WriteString(fmt.Sprintln(err))
				f.Write([]byte{'\n'})
				f.WriteString(string(buf[:n]))
			}
		}()
		f(iargs...)
	}()
}
